The Java Data Objects (JDOs) specification defines a persistence mechanism in which the Java language is used to persist and retrieve data. The JDO specification refers to any of the JDO specifications including, for example, Java Specification Request (JSR)-000012 entitled, “Java Data Objects.” A JDO persistence capable class (or, for ease of reference, a JDO) is an object that can be stored in and retrieved from a persistent data store, for example, a database. Typically, a JDO is mapped to a database table and each field of the JDO is mapped to a column of the database.
Operations on a JDO can be performed as part of a transaction. Transactions are important for maintaining data integrity. They are used to group operations into units of work in an all-or-nothing manner. Transactions have the following qualities, commonly referred to as ACID:                Atomicity—refers to the all-or-nothing property of a transaction. Either every data update in the transaction completes successfully, or they all fail, leaving the data store in its original state. A transaction cannot be only partially successful.        Consistency—each transaction leaves the data store in a consistent state.        Isolation—transactions are isolated from each other. An application reading persistent data in one transaction cannot detect modifications being made to that data in other concurrent uncompleted transactions. Likewise, updates made in one transaction cannot conflict with updates being made in another concurrent transaction. Conflicts are resolved according to whether pessimistic or optimistic transactions are used, as described below.        Durability—the effects of successful transactions are durable; that is, the updates made to persistent data last for the lifetime of the data store.        
The JDO standard defines two transaction management strategies: optimistic transactions (an optional JDO feature) and data store transactions (non-optimistic, or “pessimistic”, transactions). Pessimistic transactions generally lock the data store records on which they operate, preventing other concurrent transactions from using the same data. This approach guarantees avoiding conflicts between transactions, but consumes a lot of database resources, that is, makes the resources unavailable to other, concurrent, transactions. Additionally, locking records can result in a deadlock, a situation in which two transactions are both waiting for the other to release its locks before completing. The result of a deadlock is data store-dependent, but typically one transaction is rolled back after some specified time out interval, and an exception is thrown.
Optimistic transactions consume fewer resources than pessimistic transactions, at the expense of reliability. With optimistic transactions, an application performs operations on persistent data outside a transaction or before a commit is done using a short local data store, e.g., in memory, transaction. At commit time, persistent data may be verified against the current contents of the data store to ensure that the state of the data store is the same as it was at the beginning of the transaction. In general, optimistic transactions do not lock the data store records, so two transactions might change separate copies of the same persistent information at the same time, and the conflict will not be detected until one of the transactions attempts to commit the persistent data to the data store. At such time, the transaction may realize that another transaction has concurrently modified the same records (usually through a timestamp or versioning system), and will throw an appropriate exception. Optimistic transactions still maintain data integrity; they simply are more likely to fail in concurrent transaction situations.
As indicated above, optimistic transactions execute each operation on the data store as a separate transaction (and possibly a different connection) and data may be retrieved from a cache (a local data store) instead of a database (the data store). The data is available in a cache shared by all persistent managers, so no database access is required. In optimistic transactions, the cache improves application performance by reducing database access. Moreover, there is less lock contention at the database level. Additionally, an application may be able to run with a smaller connection pool as each connection is used for a much shorter time. Applications may use optimistic transactions to avoid holding database locks for a long time.
With pessimistic transactions, the same connection is used for all operations and a commit to the data store is performed only when the JDO transaction commits. Pessimistic transactions are useful when database locks must be maintained during the transaction while optimistic transactions offer better performance through caching and less database lock contention.
Pessimistic transactions operate on persistent data using a data store transaction, that is, between the first data access until commit, there is an active data store transaction. Relying on the transactional data store context means that the data store isolation level will determine whether implicit locks are guaranteed or not upon a certain operation to the data store. Thus, pessimistic transactions may exhibit a very datastore-dependent behaviour, since isolation levels may be implemented differently depending on different databases being accessed. It is not possible, for example, using a structured query language (SQL), to abstract the data store vendor's isolation implementation. Another drawback is that requiring a database lock requires waiting until the lock is granted, which can cause delays in transactions. Furthermore, a lock cannot be acquired prior to performing operations to the data store.